﻿/**
*	CTP.as
*	版权：广东工业大学 计算机科学与技术9班 黄平 3105007170 <jxxghp@163.com>
*/
package {
	import flash.system.*;
    import flash.display.*;
    import flash.events.*;
    import flash.external.*;
    import flash.media.*;
    import flash.net.*;
    import flash.utils.*;
    import flash.errors.*;
	import flash.text.*;
	
	public class CTP extends Sprite {
		private var Debug = true;
		
		private var url:String = null;
        private var soundFactory:Sound = null;
        private var soundChannel:SoundChannel = null;
		private var totalLength:Number;
		private var isLoaded:Boolean = false;
		private var output:TextField;
		private var lastPosition:Number;
		private var lastVolume:Number = 1;
		//
		public function CTP() {
			output = new TextField();
            output.y = 0;
            output.width = 320;
            output.height = 240;
            output.multiline = true;
            output.wordWrap = true;
            output.border = false;
            output.text = "Initializing...\n";
            addChild(output);
			
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
			
			if (ExternalInterface.available) {
				try{
					ExternalInterface.addCallback("cLoad", cLoad);
					ExternalInterface.addCallback("cPlay", cPlay);
					ExternalInterface.addCallback("cStop", cStop);
					ExternalInterface.addCallback("cStopAll", cStopAll);
					ExternalInterface.addCallback("cClose", cClose);
					ExternalInterface.addCallback("setPan", setPan);
					ExternalInterface.addCallback("setVolume", setVolume);
					ExternalInterface.addCallback("getCurPosition", getCurPosition);
					ExternalInterface.addCallback("getTotalLength", getTotalLength);
					ExternalInterface.addCallback("getLastPosition", getLastPosition);
					ExternalInterface.addCallback("getVolume", getVolume);
				}catch (error:SecurityError) {
                    output.appendText("A SecurityError occurred: " + error.message + "\n" );
                } catch (error:Error) {
                    output.appendText("An Error occurred: " + error.message + "\n");
                }
			} else {
				output.appendText("External interface is not available for this container." + "\n");
			}		
			
			output.appendText("Initialize Finished." + "\n");
			

			//cLoad("Test.mp3");
			//cPlay();			
        }
		
		// 加载
		public function cLoad(surl:String):void {
			if( surl == null )	return;
			this.url = surl;
			
			try{
            	var request:URLRequest = new URLRequest(url);
			}catch(err:Error) {
				writeLog("URL: " + err.message);				
			}
			
			soundFactory = new Sound();
			var context:SoundLoaderContext = new SoundLoaderContext(3000, false);
			try{
            	soundFactory.load(request, context);
			}catch(err:Error) {
				writeLog("LOAD: " + err.message);
			}
			
            soundFactory.addEventListener(ProgressEvent.PROGRESS, loadProgressHandler);
			soundFactory.addEventListener(Event.ID3, id3Handler);
			soundFactory.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			
			isLoaded = true;
			
		}
		
		// 播放
		public function cPlay(startTime:Number = 0):void {
			writeLog("PLAY!");
			try{
				soundChannel = soundFactory.play(startTime, 0, null);
				setVolume(this.lastVolume);
				soundChannel.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
			}catch(err:Error) {
				writeLog("PLAY: " + err.message);
			}
		}
		
		// 暂停
		public function cStop():void {
			writeLog("STOP!");
			try{
				soundChannel.stop();
				this.lastPosition = soundChannel.position;
			}catch(err:Error) {
				writeLog("STOP: " + err.message);
			}
			
		}
		
		// 全部停止
		public function cStopAll():void {
			writeLog("STOPALL!");
			if(SoundMixer.areSoundsInaccessible() == false) {
				try{
                    SoundMixer.stopAll();
					this.lastPosition = 0;
				}catch(err:Error) {
					writeLog("STOPALL: " + err.message);
				}
            }			
		}
		
		// 关闭
		public function cClose():void {
			writeLog("CLOSE!");
			try {
				 soundChannel.stop();
                 soundFactory.close();
				 this.lastPosition = 0;
            }catch (err:Error) {
				 writeLog("CLOSE: " + err.message);
            }
			
			isLoaded = false;
		}
		
		// 取得当前位置
		public function getCurPosition():Number {
			return soundChannel.position;			
		}
		
		// 播放完成处理
		private function soundCompleteHandler(event:Event):void {
			writeLog("COMPLETE!");
			ExternalInterface.call("JS_soundComplete");
		}
		
		// 取得总长度
		public function getTotalLength():Number {
			//writeLog(this.totalLength.toString());
			return this.totalLength;
		}
		
		// 取得上次停止位置
		public function getLastPosition():Number {
			return this.lastPosition;
		}
		
		// 加载进度处理
		private function loadProgressHandler(event:ProgressEvent):void {
            var loadTime:Number = event.bytesLoaded / event.bytesTotal;
            var loadPercent:uint = Math.round(100 * loadTime);
					
			if( loadPercent == 100 ) {
				soundFactory.removeEventListener(ProgressEvent.PROGRESS, loadProgressHandler);
				writeLog( "LOADED!" );
			}
			ExternalInterface.call("JS_loadProgress", loadPercent);

        }
		
		// IO错误处理
		private function ioErrorHandler(event:Event):void {
            writeLog("IOError: " + event);
			ExternalInterface.call("JS_ioError", event);
        }
		
		// 读取到ID3外理
		private function id3Handler(event:Event):void {
            var id3:ID3Info = soundFactory.id3;
			soundFactory.removeEventListener(Event.ID3, id3Handler);
			var id3Str = encodeUtf8(id3.artist) + "|" + encodeUtf8(id3.songName) + "|" + encodeUtf8(id3.album);
            ExternalInterface.call("JS_id3Handler", id3Str );
        }
		
		// 设置衡
        public function setPan(pan:Number):void {
            writeLog("setPan: " + pan.toFixed(2));
            var transForm:SoundTransform = soundChannel.soundTransform;
            transForm.pan = pan;
            soundChannel.soundTransform = transForm;
        }
		
		// 设置音量
        public function setVolume(volume:Number):void {
			this.lastVolume = volume;
            writeLog("setVolume: " + volume.toFixed(2));
			if(!isLoaded)	return;
            var transForm:SoundTransform = soundChannel.soundTransform;
            transForm.volume = volume;
            soundChannel.soundTransform = transForm;
        }
        
        // 取得音量
		public function getVolume():Number {
			var vol:Number = soundChannel.soundTransform.volume;
			return vol;			
		}
		
		// 输出日志到网页 
		private function writeLog(slog:String):void {
			cTrace( slog );
			ExternalInterface.call("JS_writeLog", slog);
		}
		
		// 输出日志到调试窗口
		private function cTrace(stext:String):void {
			if( this.Debug == true)	trace( stext );	
		}
		
		// 编码转换
		private function encodeUtf8(str : String):String {
			if(str == null)	return "";
   			var oriByteArr : ByteArray = new ByteArray();
   			oriByteArr.writeUTFBytes (str);
   			var tempByteArr : ByteArray = new ByteArray();
   			//trace(str);
   			for (var i = 0; i<oriByteArr.length; i++) {
    			if (oriByteArr[i] == 194) {
     				tempByteArr.writeByte(oriByteArr[i+1]);
     				i++;
    			} else if (oriByteArr[i] == 195) {
     				tempByteArr.writeByte(oriByteArr[i+1] + 64);
    				i++;
    			} else {
     				tempByteArr.writeByte(oriByteArr[i]);
    			}
   			}
   			tempByteArr.position = 0;
   			return tempByteArr.readMultiByte(tempByteArr.bytesAvailable,"chinese");
		}
		
		// 播放进度
		private function onEnterFrame(event:Event):void {		
			if( !isLoaded )	return;
			
			var loaded:int = soundFactory.bytesLoaded;           
            var total:int = soundFactory.bytesTotal;            
            var tlength:int = soundFactory.length; 			 
			var position:int = soundChannel.position;
			
			var percentBuffered:Number = loaded / total; 
			
			tlength /= percentBuffered;   

			this.totalLength = tlength;

			var percentPlayed:Number = position / tlength;
			//writeLog(tlength.toString());	
			if(percentPlayed)	ExternalInterface.call("JS_onEnterFrame", percentPlayed);
			
		}
	}
}